package module

import (
	"fmt"
	"generatorserver/internal/gcs"
	"math/rand"
	"publiclib/cache"
	"sync"
	"time"

	"github.com/gomodule/redigo/redis"
	log "github.com/sirupsen/logrus"
)

const (
	//两位数的最大值
	MAX_TWO_LEN  = 90
	MAX_FOUR_LEN = 9999
)

var (
	//chan 缓存大小目前为90个
	chTwoLen  = make(chan int, MAX_TWO_LEN)
	chTwoLen2 = make(chan int, MAX_TWO_LEN)
	chFourLen = make(chan int, 200)
	twoNum    = make([]int, 0, MAX_TWO_LEN)
)

//初始两位数的切片
func init() {
	for i := 10; i <= 99; i++ {
		twoNum = append(twoNum, i)
	}
	go generateTwoLenInt()
	go generateTwoLenInt2()
	go generateFourLenInt()
}

// ---

const (
	SERVER_ID_KEY = gcs.AppName
)

var (
	// 本服务的id值
	serverId     uint8 = 0
	serverIdRand *rand.Rand
	serverIdOnce = &sync.Once{}
)

func getServerId() uint8 {
	if serverId == 0 {
		serverIdOnce.Do(func() {
			serverIdRand = rand.New(rand.NewSource(time.Now().UnixNano()))

			conn := cache.GetRedis()
			defer conn.Close()
			// 初始值
			bn, _ := redis.Int(conn.Do("SETNX", SERVER_ID_KEY, 0))
			if bn == 1 {
				serverId = 1
			} else {
				//原子性的自增1
				si, err := redis.Int(conn.Do("INCR", SERVER_ID_KEY))
				if err != nil {
					log.Error("getServerId.INCR", SERVER_ID_KEY, err)
					serverId = uint8(rand.Intn(9) + 1)
				}
				serverId = uint8(si%99) + 1
			}
			log.Info("SERVER_ID_KEY:", serverId)
		})
	}
	return serverId
}

// -----

// 初始两位数生成器
func generateTwoLenInt() {
	i := 0
	for i < MAX_TWO_LEN {
		chTwoLen <- twoNum[i]
		if i+1 >= MAX_TWO_LEN {
			i = 0
		} else {
			i++
		}
	}
}

// 获取下一个两位数
func getNextTwoLenInt() int {
	return <-chTwoLen
}

// 初始两位数生成器2
func generateTwoLenInt2() {
	i := 0
	for i < MAX_TWO_LEN {
		chTwoLen2 <- twoNum[i]
		if i+1 >= MAX_TWO_LEN {
			i = 0
		} else {
			i++
		}
	}
}

func getNextTwoLenInt2() int {
	return <-chTwoLen2
}

// 初始4位数生成器
func generateFourLenInt() {
	i := 1001
	for i < MAX_FOUR_LEN {
		chFourLen <- i
		if i+1 >= MAX_FOUR_LEN {
			i = 1001
		} else {
			i++
		}
	}
}

func getNextFourLenInt() int {
	return <-chFourLen
}

// 更好的精度,1秒中重复的机率可取90*1000
func generateNoceStrV2(prefix string) string {
	t1 := time.Now()
	idxNo := getServerId()
	// 采用纳秒/1e6
	return fmt.Sprintf("%s%d%d%.2d", prefix, t1.UnixNano()/1e6, getNextTwoLenInt(), idxNo)
}

// 5 + 12 + 9 + 2 + 2 = 30
func GenerateNumUuid(prefix string) string {
	t1 := time.Now()
	idxNo := getServerId()
	return fmt.Sprintf("%s%s%.9d%d%.2d", prefix, t1.Format("060102150405"), t1.Nanosecond(), serverIdRand.Intn(89)+10, idxNo)
}

// v2使用自增生产器
func GenerateNumUuidV2(prefix string) string {
	t1 := time.Now()
	idxNo := getServerId()
	return fmt.Sprintf("%s%s%.9d%d%.2d", prefix, t1.Format("060102150405"), t1.Nanosecond(), getNextTwoLenInt2(), idxNo)
}
